home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / FractalExplorer / Dialogs.c next >
Encoding:
C/C++ Source or Header  |  2003-05-08  |  55.7 KB  |  2,001 lines

  1. #include "config.h"
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8.  
  9. #include <libgimp/gimpui.h>
  10.  
  11. #include "FractalExplorer.h"
  12. #include "Dialogs.h"
  13. #include "Events.h"
  14.  
  15. #include "logo.h"
  16.  
  17. #include "libgimp/stdplugins-intl.h"
  18.  
  19.  
  20. #ifdef G_OS_WIN32
  21. #  include <io.h>
  22. #  ifndef W_OK
  23. #    define W_OK 2
  24. #  endif
  25. #  ifndef S_ISDIR
  26. #    define S_ISDIR(m) ((m) & _S_IFDIR)
  27. #  endif
  28. #  ifndef S_ISREG
  29. #    define S_ISREG(m) ((m) & _S_IFREG)
  30. #  endif
  31. #endif
  32.  
  33. static gdouble *gradient_samples = NULL;
  34. static gchar   *gradient_name    = NULL;
  35.  
  36. /**********************************************************************
  37.  FORWARD DECLARATIONS
  38.  *********************************************************************/
  39.  
  40. static void explorer_logo_dialog (void);
  41.  
  42. /**********************************************************************
  43.  CALLBACKS
  44.  *********************************************************************/
  45.  
  46. static void
  47. dialog_ok_callback (GtkWidget *widget,
  48.             gpointer   data)
  49. {
  50.   wint.run = TRUE;
  51.  
  52.   gtk_widget_destroy (GTK_WIDGET (data));
  53. }
  54.  
  55. static void
  56. dialog_reset_callback (GtkWidget *widget,
  57.                gpointer   data)
  58. {
  59.   wvals.xmin = standardvals.xmin;
  60.   wvals.xmax = standardvals.xmax;
  61.   wvals.ymin = standardvals.ymin;
  62.   wvals.ymax = standardvals.ymax;
  63.   wvals.iter = standardvals.iter;
  64.   wvals.cx = standardvals.cx;
  65.   wvals.cy = standardvals.cy;
  66.  
  67.   dialog_change_scale ();
  68.   set_cmap_preview ();
  69.   dialog_update_preview ();
  70. }
  71.  
  72. static void
  73. dialog_redraw_callback (GtkWidget *widget,
  74.             gpointer   data)
  75. {
  76.   gint alwaysprev = wvals.alwayspreview;
  77.  
  78.   wvals.alwayspreview = TRUE;
  79.   set_cmap_preview();
  80.   dialog_update_preview();
  81.   wvals.alwayspreview = alwaysprev;
  82. }
  83.  
  84. static void
  85. dialog_undo_zoom_callback (GtkWidget *widget,
  86.                gpointer   data)
  87. {
  88.   if (zoomindex > 1)
  89.     {
  90.       zooms[zoomindex] = wvals;
  91.       zoomindex--;
  92.       wvals = zooms[zoomindex];
  93.       dialog_change_scale ();
  94.       set_cmap_preview ();
  95.       dialog_update_preview ();
  96.     }
  97. }
  98.  
  99. static void
  100. dialog_redo_zoom_callback (GtkWidget *widget,
  101.                gpointer   data)
  102. {
  103.   if (zoomindex < zoommax)
  104.     {
  105.       zoomindex++;
  106.       wvals = zooms[zoomindex];
  107.       dialog_change_scale ();
  108.       set_cmap_preview ();
  109.       dialog_update_preview ();
  110.     }
  111. }
  112.  
  113. static void
  114. dialog_step_in_callback (GtkWidget *widget,
  115.              gpointer   data)
  116. {
  117.   double xdifferenz;
  118.   double ydifferenz;
  119.  
  120.   if (zoomindex < zoommax)
  121.     {
  122.       zooms[zoomindex]=wvals;
  123.       zoomindex++;
  124.     }
  125.  
  126.   xdifferenz = wvals.xmax-wvals.xmin;
  127.   ydifferenz = wvals.ymax-wvals.ymin;
  128.   wvals.xmin += 1.0/6.0*xdifferenz;
  129.   wvals.ymin += 1.0/6.0*ydifferenz;
  130.   wvals.xmax -= 1.0/6.0*xdifferenz;
  131.   wvals.ymax -= 1.0/6.0*ydifferenz;
  132.   zooms[zoomindex] = wvals;
  133.  
  134.   dialog_change_scale ();
  135.   set_cmap_preview ();
  136.   dialog_update_preview ();
  137. }                /* dialog_step_in_callback */
  138.  
  139. static void
  140. dialog_step_out_callback (GtkWidget *widget,
  141.               gpointer   data)
  142. {
  143.   double xdifferenz;
  144.   double ydifferenz;
  145.  
  146.   if (zoomindex < zoommax)
  147.     {
  148.       zooms[zoomindex]=wvals;
  149.       zoomindex++;
  150.     }
  151.  
  152.   xdifferenz = wvals.xmax-wvals.xmin;
  153.   ydifferenz = wvals.ymax-wvals.ymin;
  154.   wvals.xmin -= 1.0/4.0*xdifferenz;
  155.   wvals.ymin -= 1.0/4.0*ydifferenz;
  156.   wvals.xmax += 1.0/4.0*xdifferenz;
  157.   wvals.ymax += 1.0/4.0*ydifferenz;
  158.   zooms[zoomindex] = wvals;
  159.  
  160.   dialog_change_scale ();
  161.   set_cmap_preview ();
  162.   dialog_update_preview ();
  163. }
  164.  
  165. static void
  166. explorer_toggle_update (GtkWidget *widget,
  167.             gpointer   data)
  168. {
  169.   gimp_toggle_button_update (widget, data);
  170.  
  171.   set_cmap_preview ();
  172.   dialog_update_preview ();
  173. }
  174.  
  175. static void
  176. explorer_radio_update  (GtkWidget *widget,
  177.             gpointer   data)
  178. {
  179.   gimp_radio_button_update (widget, data);
  180.  
  181.   set_cmap_preview ();
  182.   dialog_update_preview ();
  183. }
  184.  
  185. static void
  186. explorer_double_adjustment_update (GtkAdjustment *adjustment,
  187.                    gpointer       data)
  188. {
  189.   gimp_double_adjustment_update (adjustment, data);
  190.  
  191.   set_cmap_preview ();
  192.   dialog_update_preview ();
  193. }
  194.  
  195. static void
  196. explorer_number_of_colors_callback (GtkAdjustment *adjustment,
  197.                     gpointer       data)
  198. {
  199.   gint dummy;
  200.  
  201.   gimp_int_adjustment_update (adjustment, data);
  202.  
  203.   g_free (gradient_samples);
  204.  
  205.   if (gradient_name == NULL)
  206.     gradient_name = gimp_gradients_get_active ();
  207.  
  208.   gimp_gradients_get_gradient_data (gradient_name, &dummy, wvals.ncolors,
  209.                    &gradient_samples);
  210.  
  211.   set_cmap_preview ();
  212.   dialog_update_preview ();
  213. }
  214.  
  215. static void
  216. explorer_gradient_select_callback (gchar    *name,
  217.                    gint      width,
  218.                    gdouble  *gradient_data,
  219.                    gint      dialog_closing,
  220.                    gpointer  data)
  221. {
  222.   gint dummy;
  223.  
  224.   g_free (gradient_name);
  225.   g_free (gradient_samples);
  226.  
  227.   gradient_name = g_strdup (name);
  228.  
  229.   gimp_gradients_get_gradient_data (gradient_name, &dummy, wvals.ncolors,
  230.                    &gradient_samples);
  231.  
  232.   if (wvals.colormode == 1)
  233.     {
  234.       set_cmap_preview();
  235.       dialog_update_preview(); 
  236.     }
  237. }
  238.  
  239. /**********************************************************************
  240.  FUNCTION: explorer_dialog
  241.  *********************************************************************/
  242.  
  243. gint
  244. explorer_dialog (void)
  245. {
  246.   GtkWidget *dialog;
  247.   GtkWidget *top_hbox;
  248.   GtkWidget *left_vbox;
  249.   GtkWidget *abox;
  250.   GtkWidget *vbox;
  251.   GtkWidget *hbbox;
  252.   GtkWidget *frame;
  253.   GtkWidget *pframe;
  254.   GtkWidget *toggle;
  255.   GtkWidget *toggle_vbox;
  256.   GtkWidget *toggle_vbox2;
  257.   GtkWidget *toggle_vbox3;
  258.   GtkWidget *notebook;
  259.   GtkWidget *hbox;
  260.   GtkWidget *table;
  261.   GtkWidget *button;
  262.   GtkWidget *gradient;
  263.   GtkWidget *sep;
  264.   gchar   *gradient_name;
  265.   GSList  *group = NULL;
  266.   gint     i;
  267.  
  268.   gimp_ui_init ("fractalexplorer", TRUE);
  269.  
  270.   plug_in_parse_fractalexplorer_path ();
  271.  
  272.   wint.wimage = g_new (guchar, preview_width * preview_height * 3);
  273.   elements    = g_new (DialogElements, 1);
  274.  
  275.   dialog = maindlg =
  276.     gimp_dialog_new ("Fractal Explorer <Daniel Cotting/cotting@multimania.com>",
  277.              "fractalexplorer",
  278.              gimp_standard_help_func, "filters/fractalexplorer.html",
  279.              GTK_WIN_POS_NONE,
  280.              FALSE, TRUE, FALSE,
  281.  
  282.              _("About"), explorer_logo_dialog,
  283.              NULL, NULL, NULL, FALSE, FALSE,
  284.              _("OK"), dialog_ok_callback,
  285.              NULL, NULL, NULL, TRUE, FALSE,
  286.              _("Cancel"), gtk_widget_destroy,
  287.              NULL, 1, NULL, FALSE, TRUE,
  288.  
  289.              NULL);
  290.  
  291.   gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
  292.               GTK_SIGNAL_FUNC (gtk_main_quit),
  293.               NULL);
  294.  
  295.   gimp_help_init ();
  296.  
  297.   top_hbox = gtk_hbox_new (FALSE, 6);
  298.   gtk_container_set_border_width (GTK_CONTAINER (top_hbox), 6);
  299.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_hbox,
  300.               FALSE, FALSE, 0);
  301.   gtk_widget_show (top_hbox);
  302.  
  303.   left_vbox = gtk_vbox_new (FALSE, 6);
  304.   gtk_box_pack_start (GTK_BOX (top_hbox), left_vbox, FALSE, FALSE, 0);
  305.   gtk_widget_show (left_vbox);
  306.  
  307.   /*  Preview  */
  308.   frame = gtk_frame_new (_("Preview"));
  309.   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  310.   gtk_box_pack_start (GTK_BOX (left_vbox), frame, FALSE, FALSE, 0);
  311.   gtk_widget_show (frame);
  312.  
  313.   vbox = gtk_vbox_new (FALSE, 4);
  314.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  315.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  316.   gtk_widget_show (vbox);
  317.  
  318.   abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  319.   gtk_box_pack_start (GTK_BOX (vbox), abox, FALSE, FALSE, 0);
  320.   gtk_widget_show (abox);
  321.  
  322.   pframe = gtk_frame_new (NULL);
  323.   gtk_frame_set_shadow_type (GTK_FRAME (pframe), GTK_SHADOW_IN);
  324.   gtk_container_add (GTK_CONTAINER (abox), pframe);
  325.   gtk_widget_show (pframe);
  326.  
  327.   wint.preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  328.   gtk_preview_size (GTK_PREVIEW (wint.preview), preview_width, preview_height);
  329.   gtk_container_add (GTK_CONTAINER (pframe), wint.preview);
  330.   gtk_signal_connect (GTK_OBJECT (wint.preview), "button_press_event",
  331.               (GtkSignalFunc) preview_button_press_event,
  332.               NULL);
  333.   gtk_signal_connect (GTK_OBJECT (wint.preview), "button_release_event",
  334.               (GtkSignalFunc) preview_button_release_event,
  335.               NULL);
  336.   gtk_signal_connect (GTK_OBJECT (wint.preview), "motion_notify_event",
  337.               (GtkSignalFunc) preview_motion_notify_event,
  338.               NULL);
  339.   gtk_signal_connect (GTK_OBJECT (wint.preview), "leave_notify_event",
  340.               (GtkSignalFunc) preview_leave_notify_event,
  341.               NULL);
  342.   gtk_signal_connect (GTK_OBJECT (wint.preview), "enter_notify_event",
  343.               (GtkSignalFunc) preview_enter_notify_event,
  344.               NULL);
  345.   gtk_widget_set_events (wint.preview, (GDK_BUTTON_PRESS_MASK |
  346.                     GDK_BUTTON_RELEASE_MASK |
  347.                     GDK_POINTER_MOTION_MASK |
  348.                     GDK_LEAVE_NOTIFY_MASK |
  349.                     GDK_ENTER_NOTIFY_MASK));
  350.   gtk_widget_show (wint.preview);
  351.  
  352.   toggle = gtk_check_button_new_with_label (_("Realtime Preview"));
  353.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  354.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  355.               GTK_SIGNAL_FUNC (explorer_toggle_update),
  356.               &wvals.alwayspreview);
  357.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.alwayspreview);
  358.   gtk_widget_show (toggle);
  359.   gimp_help_set_help_data (toggle, _("If you enable this option the preview "
  360.                      "will be redrawn automatically"), NULL);
  361.  
  362.   button = gtk_button_new_with_label (_("Redraw"));
  363.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  364.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  365.               GTK_SIGNAL_FUNC (dialog_redraw_callback),
  366.               dialog);
  367.   gtk_widget_show (button);
  368.   gimp_help_set_help_data (button, _("Redraw preview"), NULL);
  369.  
  370.   /*  Zoom Options  */
  371.   frame = gtk_frame_new (_("Zoom Options"));
  372.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  373.   gtk_box_pack_end (GTK_BOX (left_vbox), frame, FALSE, FALSE, 0);
  374.   gtk_widget_show (frame);
  375.  
  376.   vbox = gtk_vbox_new(FALSE, 0);
  377.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  378.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  379.   gtk_widget_show (vbox);
  380.  
  381.   button = gtk_button_new_with_label (_("Undo Zoom"));
  382.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  383.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  384.               GTK_SIGNAL_FUNC (dialog_undo_zoom_callback),
  385.               dialog);
  386.   gtk_widget_show (button);
  387.   gimp_help_set_help_data (button, _("Undo last zoom"), NULL);
  388.  
  389.   button = gtk_button_new_with_label (_("Redo Zoom"));
  390.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  391.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  392.               GTK_SIGNAL_FUNC (dialog_redo_zoom_callback),
  393.               dialog);
  394.   gtk_widget_show (button);
  395.   gimp_help_set_help_data (button, _("Redo last zoom"), NULL);
  396.  
  397.   button = gtk_button_new_with_label (_("Step In"));
  398.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  399.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  400.               GTK_SIGNAL_FUNC (dialog_step_in_callback),
  401.               dialog);
  402.   gtk_widget_show (button);
  403.  
  404.   button = gtk_button_new_with_label (_("Step Out"));
  405.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  406.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  407.               GTK_SIGNAL_FUNC (dialog_step_out_callback),
  408.               dialog);
  409.   gtk_widget_show (button);
  410.  
  411.  
  412.   /*  Create notebook  */
  413.   notebook = gtk_notebook_new ();
  414.   gtk_box_pack_start (GTK_BOX (top_hbox), notebook, FALSE, FALSE, 0);
  415.   gtk_widget_show (notebook);
  416.  
  417.   /*  "Parameters" page  */
  418.   vbox = gtk_vbox_new (FALSE, 4);
  419.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  420.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox,
  421.                 gtk_label_new (_("Parameters")));
  422.   gtk_widget_show (vbox);
  423.  
  424.   frame = gtk_frame_new (_("Fractal Parameters"));
  425.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  426.   gtk_widget_show (frame);
  427.  
  428.   table = gtk_table_new (8, 3, FALSE);
  429.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  430.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  431.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  432.   gtk_table_set_row_spacing (GTK_TABLE (table), 6, 4);
  433.   gtk_container_add (GTK_CONTAINER (frame), table);
  434.   gtk_widget_show (table);
  435.  
  436.   elements->xmin =
  437.     gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  438.               _("XMIN:"), SCALE_WIDTH, 100,
  439.               wvals.xmin, -3, 3, 0.001, 0.01, 5,
  440.               TRUE, 0, 0,
  441.               _("Change the first (minimal) x-coordinate "
  442.                 "delimitation"), NULL);
  443.   gtk_signal_connect (GTK_OBJECT (elements->xmin), "value_changed",
  444.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  445.               &wvals.xmin);
  446.  
  447.   elements->xmax =
  448.     gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
  449.               _("XMAX:"), SCALE_WIDTH, 100,
  450.               wvals.xmax, -3, 3, 0.001, 0.01, 5,
  451.               TRUE, 0, 0,
  452.               _("Change the second (maximal) x-coordinate "
  453.                 "delimitation"), NULL);
  454.   gtk_signal_connect (GTK_OBJECT (elements->xmax), "value_changed",
  455.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  456.               &wvals.xmax);
  457.  
  458.   elements->ymin =
  459.     gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
  460.               _("YMIN:"), SCALE_WIDTH, 100,
  461.               wvals.ymin, -3, 3, 0.001, 0.01, 5,
  462.               TRUE, 0, 0,
  463.               _("Change the first (minimal) y-coordinate "
  464.                 "delimitation"), NULL);
  465.   gtk_signal_connect (GTK_OBJECT (elements->ymin), "value_changed",
  466.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  467.               &wvals.ymin);
  468.  
  469.   elements->ymax =
  470.     gimp_scale_entry_new (GTK_TABLE (table), 0, 3,
  471.               _("YMAX:"), SCALE_WIDTH, 100,
  472.               wvals.ymax, -3, 3, 0.001, 0.01, 5,
  473.               TRUE, 0, 0,
  474.               _("Change the second (maximal) y-coordinate "
  475.                 "delimitation"), NULL);
  476.   gtk_signal_connect (GTK_OBJECT (elements->ymax), "value_changed",
  477.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  478.               &wvals.ymax);
  479.  
  480.   elements->iter =
  481.     gimp_scale_entry_new (GTK_TABLE (table), 0, 4,
  482.               _("ITER:"), SCALE_WIDTH, 100,
  483.               wvals.iter, 0, 1000, 1, 10, 5,
  484.               TRUE, 0, 0,
  485.               _("Change the iteration value. The higher it "
  486.                 "is, the more details will be calculated, "
  487.                 "which will take more time"), NULL);
  488.   gtk_signal_connect (GTK_OBJECT (elements->iter), "value_changed",
  489.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  490.               &wvals.iter);
  491.  
  492.   elements->cx =
  493.     gimp_scale_entry_new (GTK_TABLE (table), 0, 5,
  494.               _("CX:"), SCALE_WIDTH, 100,
  495.               wvals.cx, -2.5, 2.5, 0.001, 0.01, 5,
  496.               TRUE, 0, 0,
  497.               _("Change the CX value (changes aspect of "
  498.                 "fractal, active with every fractal but "
  499.                 "Mandelbrot and Sierpinski)"), NULL);
  500.   gtk_signal_connect (GTK_OBJECT (elements->cx), "value_changed",
  501.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  502.               &wvals.cx);
  503.  
  504.   elements->cy =
  505.     gimp_scale_entry_new (GTK_TABLE (table), 0, 6,
  506.               _("CY:"), SCALE_WIDTH, 100,
  507.               wvals.cy, -2.5, 2.5, 0.001, 0.01, 5,
  508.               TRUE, 0, 0,
  509.               _("Change the CY value (changes aspect of "
  510.                 "fractal, active with every fractal but "
  511.                 "Mandelbrot and Sierpinski)"), NULL);
  512.   gtk_signal_connect (GTK_OBJECT (elements->cy), "value_changed",
  513.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  514.               &wvals.cy);
  515.  
  516.   hbbox = gtk_hbox_new (FALSE, 4);
  517.   gtk_table_attach_defaults (GTK_TABLE (table), hbbox, 0, 3, 7, 8);
  518.   gtk_widget_show (hbbox);
  519.  
  520.   button = gtk_button_new_with_label (_("Load"));
  521.   gtk_box_pack_start (GTK_BOX (hbbox), button, TRUE, TRUE, 0);
  522.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  523.               GTK_SIGNAL_FUNC (create_load_file_selection),
  524.               dialog);
  525.   gtk_widget_show (button);
  526.   gimp_help_set_help_data (button, _("Load a fractal from file"), NULL);
  527.  
  528.   button = gtk_button_new_with_label (_("Reset"));
  529.   gtk_box_pack_start (GTK_BOX (hbbox), button, TRUE, TRUE, 0);
  530.   gtk_signal_connect (GTK_OBJECT(button), "clicked",
  531.               GTK_SIGNAL_FUNC (dialog_reset_callback),
  532.               dialog);
  533.   gtk_widget_show (button);
  534.   gimp_help_set_help_data (button, _("Reset parameters to default values"),
  535.                NULL);
  536.  
  537.   button = gtk_button_new_with_label (_("Save"));
  538.   gtk_box_pack_start (GTK_BOX (hbbox), button, TRUE, TRUE, 0);
  539.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  540.               GTK_SIGNAL_FUNC (create_file_selection),
  541.               dialog);
  542.   gtk_widget_show (button);
  543.   gimp_help_set_help_data (button, _("Save active fractal to file"), NULL);
  544.     
  545.   /*  Fractal type toggle box  */
  546.   frame = gtk_frame_new (_("Fractal Type"));
  547.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  548.  
  549.   hbox = gtk_hbox_new (FALSE, 6);
  550.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  551.   gtk_container_add (GTK_CONTAINER (frame), hbox);
  552.  
  553.   toggle_vbox =
  554.     gimp_radio_group_new2 (FALSE, NULL,
  555.                explorer_radio_update,
  556.                &wvals.fractaltype,
  557.                GINT_TO_POINTER (wvals.fractaltype),
  558.  
  559.                _("Mandelbrot"), GINT_TO_POINTER (TYPE_MANDELBROT),
  560.                &(elements->type[TYPE_MANDELBROT]),
  561.                _("Julia"), GINT_TO_POINTER (TYPE_JULIA),
  562.                &(elements->type[TYPE_JULIA]),
  563.                _("Barnsley 1"), GINT_TO_POINTER (TYPE_BARNSLEY_1),
  564.                &(elements->type[TYPE_BARNSLEY_1]),
  565.                _("Barnsley 2"), GINT_TO_POINTER (TYPE_BARNSLEY_2),
  566.                &(elements->type[TYPE_BARNSLEY_2]),
  567.                _("Barnsley 3"), GINT_TO_POINTER (TYPE_BARNSLEY_3),
  568.                &(elements->type[TYPE_BARNSLEY_3]),
  569.                _("Spider"), GINT_TO_POINTER (TYPE_SPIDER),
  570.                &(elements->type[TYPE_SPIDER]),
  571.                _("Man'o'war"), GINT_TO_POINTER (TYPE_MAN_O_WAR),
  572.                &(elements->type[TYPE_MAN_O_WAR]),
  573.                _("Lambda"), GINT_TO_POINTER (TYPE_LAMBDA),
  574.                &(elements->type[TYPE_LAMBDA]),
  575.                _("Sierpinski"), GINT_TO_POINTER (TYPE_SIERPINSKI),
  576.                &(elements->type[TYPE_SIERPINSKI]),
  577.  
  578.                NULL);
  579.  
  580.   toggle_vbox2 = gtk_vbox_new (FALSE, 1);
  581.   for (i = TYPE_BARNSLEY_2; i <= TYPE_SPIDER; i++)
  582.     {
  583.       gtk_object_ref (GTK_OBJECT (elements->type[i]));
  584.       gtk_widget_hide (elements->type[i]);
  585.       gtk_container_remove (GTK_CONTAINER (toggle_vbox), elements->type[i]);
  586.       gtk_box_pack_start (GTK_BOX (toggle_vbox2), elements->type[i],
  587.               FALSE, FALSE, 0);
  588.       gtk_widget_show (elements->type[i]);
  589.       gtk_object_unref (GTK_OBJECT (elements->type[i]));
  590.     }
  591.  
  592.   toggle_vbox3 = gtk_vbox_new (FALSE, 1);
  593.   for (i = TYPE_MAN_O_WAR; i <= TYPE_SIERPINSKI; i++)
  594.     {
  595.       gtk_object_ref (GTK_OBJECT (elements->type[i]));
  596.       gtk_widget_hide (elements->type[i]);
  597.       gtk_container_remove (GTK_CONTAINER (toggle_vbox), elements->type[i]);
  598.       gtk_box_pack_start (GTK_BOX (toggle_vbox3), elements->type[i],
  599.               FALSE, FALSE, 0);
  600.       gtk_widget_show (elements->type[i]);
  601.       gtk_object_unref (GTK_OBJECT (elements->type[i]));
  602.     }
  603.  
  604.   gtk_container_set_border_width (GTK_CONTAINER (toggle_vbox), 0);
  605.   gtk_box_pack_start (GTK_BOX (hbox), toggle_vbox, FALSE, FALSE, 0);
  606.   gtk_widget_show (toggle_vbox);
  607.  
  608.   gtk_box_pack_start (GTK_BOX (hbox), toggle_vbox2, FALSE, FALSE, 0);
  609.   gtk_widget_show (toggle_vbox2);
  610.  
  611.   gtk_box_pack_start (GTK_BOX (hbox), toggle_vbox3, FALSE, FALSE, 0);
  612.   gtk_widget_show (toggle_vbox3);
  613.  
  614.   gtk_widget_show (hbox);
  615.   gtk_widget_show (frame);
  616.  
  617.   /*  Color page  */
  618.   vbox = gtk_vbox_new (FALSE, 4);
  619.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  620.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox,
  621.                 gtk_label_new (_("Colors")));
  622.   gtk_widget_show (vbox);
  623.  
  624.   /*  Number of Colors frame  */
  625.   frame = gtk_frame_new (_("Number of Colors"));
  626.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  627.   gtk_widget_show (frame);
  628.  
  629.   table = gtk_table_new (2, 3, FALSE);
  630.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  631.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  632.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  633.   gtk_container_add (GTK_CONTAINER (frame), table);
  634.   gtk_widget_show (table);
  635.  
  636.   elements->ncol =
  637.     gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  638.               _("Number of Colors:"), SCALE_WIDTH, 0,
  639.               wvals.ncolors, 2, MAXNCOLORS, 1, 10, 0,
  640.               TRUE, 0, 0,
  641.               _("Change the number of colors in the mapping"),
  642.               NULL);
  643.   gtk_signal_connect (GTK_OBJECT (elements->ncol), "value_changed",
  644.               GTK_SIGNAL_FUNC (explorer_number_of_colors_callback),
  645.               &wvals.ncolors);
  646.  
  647.   elements->useloglog = toggle =
  648.     gtk_check_button_new_with_label (_("Use loglog Smoothing"));
  649.   gtk_table_attach_defaults (GTK_TABLE (table), toggle, 0, 3, 1, 2);
  650.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  651.               (GtkSignalFunc) explorer_toggle_update,
  652.               &wvals.useloglog);
  653.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.useloglog);
  654.   gtk_widget_show (toggle);
  655.   gimp_help_set_help_data (toggle, _("Use log log smoothing to eliminate "
  656.                      "\"banding\" in the result"), NULL);
  657.  
  658.   /*  Color Density frame  */
  659.   frame = gtk_frame_new (_("Color Density"));
  660.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  661.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  662.   gtk_widget_show (frame);
  663.  
  664.   table = gtk_table_new (3, 3, FALSE);
  665.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  666.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  667.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  668.   gtk_container_add (GTK_CONTAINER (frame), table);
  669.   gtk_widget_show (table);
  670.  
  671.   elements->red =
  672.     gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  673.               _("Red:"), SCALE_WIDTH, 0,
  674.               wvals.redstretch, 0, 1, 0.01, 0.1, 2,
  675.               TRUE, 0, 0,
  676.               _("Change the intensity of the red channel"), NULL);
  677.   gtk_signal_connect (GTK_OBJECT (elements->red), "value_changed",
  678.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  679.               &wvals.redstretch);
  680.  
  681.   elements->green =
  682.     gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
  683.               _("Green:"), SCALE_WIDTH, 0,
  684.               wvals.greenstretch, 0, 1, 0.01, 0.1, 2,
  685.               TRUE, 0, 0,
  686.               _("Change the intensity of the green channel"), NULL);
  687.   gtk_signal_connect (GTK_OBJECT (elements->green), "value_changed",
  688.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  689.               &wvals.greenstretch);
  690.  
  691.   elements->blue =
  692.     gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
  693.               _("Blue:"), SCALE_WIDTH, 0,
  694.               wvals.bluestretch, 0, 1, 0.01, 0.1, 2,
  695.               TRUE, 0, 0,
  696.               _("Change the intensity of the blue channel"), NULL);
  697.   gtk_signal_connect (GTK_OBJECT (elements->blue), "value_changed",
  698.               GTK_SIGNAL_FUNC (explorer_double_adjustment_update),
  699.               &wvals.bluestretch);
  700.  
  701.   /*  Color Function frame  */
  702.   frame = gtk_frame_new (_("Color Function"));
  703.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  704.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  705.   gtk_widget_show (frame);
  706.  
  707.   hbox = gtk_hbox_new (FALSE, 6);
  708.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  709.   gtk_container_add (GTK_CONTAINER (frame), hbox);
  710.   gtk_widget_show (hbox);
  711.  
  712.   /*  Redmode radio frame  */
  713.   frame = gimp_radio_group_new2 (TRUE, _("Red"),
  714.                  explorer_radio_update,
  715.                  &wvals.redmode, GINT_TO_POINTER (wvals.redmode),
  716.  
  717.                  _("Sine"), GINT_TO_POINTER (SINUS),
  718.                  &elements->redmode[SINUS],
  719.                  _("Cosine"), GINT_TO_POINTER (COSINUS),
  720.                  &elements->redmode[COSINUS],
  721.                  _("None"), GINT_TO_POINTER (NONE),
  722.                  &elements->redmode[NONE],
  723.  
  724.                  NULL);
  725.   gimp_help_set_help_data (elements->redmode[SINUS],
  726.                _("Use sine-function for this color component"),
  727.                NULL);
  728.   gimp_help_set_help_data (elements->redmode[COSINUS],
  729.                _("Use cosine-function for this color "
  730.                  "component"), NULL);
  731.   gimp_help_set_help_data (elements->redmode[NONE],
  732.                _("Use linear mapping instead of any "
  733.                  "trigonometrical function for this color "
  734.                  "channel"), NULL);
  735.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  736.   gtk_widget_show (frame);
  737.  
  738.   toggle_vbox = GTK_BIN (frame)->child;
  739.  
  740.   elements->redinvert = toggle =
  741.     gtk_check_button_new_with_label (_("Inversion"));
  742.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.redinvert);
  743.   gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
  744.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  745.               GTK_SIGNAL_FUNC (explorer_toggle_update),
  746.               &wvals.redinvert);
  747.   gtk_widget_show (toggle);
  748.   gimp_help_set_help_data (toggle,
  749.                _("If you enable this option higher color values "
  750.                  "will be swapped with lower ones and vice "
  751.                  "versa"), NULL);
  752.  
  753.   /*  Greenmode radio frame  */
  754.   frame = gimp_radio_group_new2 (TRUE, _("Green"),
  755.                  explorer_radio_update,
  756.                  &wvals.greenmode, GINT_TO_POINTER (wvals.greenmode),
  757.  
  758.                  _("Sine"), GINT_TO_POINTER (SINUS),
  759.                  &elements->greenmode[SINUS],
  760.                  _("Cosine"), GINT_TO_POINTER (COSINUS),
  761.                  &elements->greenmode[COSINUS],
  762.                  _("None"), GINT_TO_POINTER (NONE),
  763.                  &elements->greenmode[NONE],
  764.  
  765.                  NULL);
  766.   gimp_help_set_help_data (elements->greenmode[SINUS],
  767.                _("Use sine-function for this color component"),
  768.                NULL);
  769.   gimp_help_set_help_data (elements->greenmode[COSINUS],
  770.                _("Use cosine-function for this color "
  771.                  "component"), NULL);
  772.   gimp_help_set_help_data (elements->greenmode[NONE],
  773.                _("Use linear mapping instead of any "
  774.                  "trigonometrical function for this color "
  775.                  "channel"), NULL);
  776.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  777.   gtk_widget_show (frame);
  778.  
  779.   toggle_vbox = GTK_BIN (frame)->child;
  780.  
  781.   elements->greeninvert = toggle =
  782.     gtk_check_button_new_with_label (_("Inversion"));
  783.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), wvals.greeninvert);
  784.   gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
  785.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  786.               GTK_SIGNAL_FUNC (explorer_toggle_update),
  787.               &wvals.greeninvert);
  788.   gtk_widget_show (toggle);
  789.   gimp_help_set_help_data (toggle,
  790.                _("If you enable this option higher color values "
  791.                  "will be swapped with lower ones and vice "
  792.                  "versa"), NULL);
  793.  
  794.   /*  Bluemode radio frame  */
  795.   frame = gimp_radio_group_new2 (TRUE, _("Blue"),
  796.                  explorer_radio_update,
  797.                  &wvals.bluemode, GINT_TO_POINTER (wvals.bluemode),
  798.  
  799.                  _("Sine"), GINT_TO_POINTER (SINUS),
  800.                  &elements->bluemode[SINUS],
  801.                  _("Cosine"), GINT_TO_POINTER (COSINUS),
  802.                  &elements->bluemode[COSINUS],
  803.                  _("None"), GINT_TO_POINTER (NONE),
  804.                  &elements->bluemode[NONE],
  805.  
  806.                  NULL);
  807.   gimp_help_set_help_data (elements->bluemode[SINUS],
  808.                _("Use sine-function for this color component"),
  809.                NULL);
  810.   gimp_help_set_help_data (elements->bluemode[COSINUS],
  811.                _("Use cosine-function for this color "
  812.                  "component"), NULL);
  813.   gimp_help_set_help_data (elements->bluemode[NONE],
  814.                _("Use linear mapping instead of any "
  815.                  "trigonometrical function for this color "
  816.                  "channel"), NULL);
  817.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  818.   gtk_widget_show (frame);
  819.  
  820.   toggle_vbox = GTK_BIN (frame)->child;
  821.  
  822.   elements->blueinvert = toggle =
  823.     gtk_check_button_new_with_label (_("Inversion"));
  824.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON( toggle), wvals.blueinvert);
  825.   gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
  826.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  827.               GTK_SIGNAL_FUNC (explorer_toggle_update),
  828.               &wvals.blueinvert);
  829.   gtk_widget_show (toggle);
  830.   gimp_help_set_help_data (toggle,
  831.                _("If you enable this option higher color values "
  832.                  "will be swapped with lower ones and vice "
  833.                  "versa"), NULL);
  834.  
  835.   /*  Colormode toggle box  */
  836.   frame = gtk_frame_new (_("Color Mode"));
  837.   gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  838.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  839.   gtk_widget_show (frame);
  840.  
  841.   toggle_vbox = gtk_vbox_new (FALSE, 2);
  842.   gtk_container_set_border_width (GTK_CONTAINER (toggle_vbox), 2);
  843.   gtk_container_add (GTK_CONTAINER (frame), toggle_vbox);
  844.   gtk_widget_show (toggle_vbox);
  845.  
  846.   toggle = elements->colormode[0] =
  847.     gtk_radio_button_new_with_label (group, _("As Specified above"));
  848.   group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  849.   gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
  850.   gtk_object_set_user_data (GTK_OBJECT (toggle), GINT_TO_POINTER (0));
  851.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  852.               GTK_SIGNAL_FUNC (explorer_radio_update),
  853.               &wvals.colormode);
  854.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  855.                 wvals.colormode == 0);
  856.   gtk_widget_show (toggle);
  857.   gimp_help_set_help_data (toggle,
  858.                _("Create a color-map with the options you "
  859.                  "specified above (color density/function). The "
  860.                  "result is visible in the preview image"), NULL);
  861.  
  862.   hbox = gtk_hbox_new (FALSE, 6);
  863.   gtk_box_pack_start (GTK_BOX (toggle_vbox), hbox, FALSE, FALSE, 0);
  864.   gtk_widget_show (hbox);
  865.  
  866.   toggle = elements->colormode[1] =
  867.     gtk_radio_button_new_with_label (group,
  868.                      _("Apply Active Gradient to Final Image"));
  869.   group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  870.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
  871.   gtk_object_set_user_data (GTK_OBJECT (toggle), GINT_TO_POINTER (1));
  872.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  873.               GTK_SIGNAL_FUNC (explorer_radio_update),
  874.               &wvals.colormode);
  875.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  876.                 wvals.colormode == 1);
  877.   gtk_widget_show (toggle);
  878.   gimp_help_set_help_data (toggle,
  879.                _("Create a color-map using a gradient from "
  880.                  "the gradient editor"), NULL);
  881.  
  882.   gradient_name = gimp_gradients_get_active ();
  883.   gradient_samples = gimp_gradients_sample_uniform (wvals.ncolors);
  884.   gradient = gimp_gradient_select_widget (_("FractalExplorer Gradient"),
  885.                       gradient_name,
  886.                       explorer_gradient_select_callback,
  887.                       NULL);
  888.   g_free (gradient_name);
  889.   gtk_box_pack_start (GTK_BOX (hbox), gradient, FALSE, FALSE, 0);
  890.   gtk_widget_show (gradient);
  891.  
  892.   sep = gtk_hseparator_new ();
  893.   gtk_box_pack_start (GTK_BOX (toggle_vbox), sep, FALSE, FALSE, 1);
  894.   gtk_widget_show (sep);
  895.  
  896.   abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  897.   {
  898.     gint xsize, ysize;
  899.  
  900.     for (ysize = 1; ysize * ysize * ysize < 8192; ysize++) /**/;
  901.     xsize = wvals.ncolors / ysize;
  902.     while (xsize * ysize < 8192) xsize++;
  903.  
  904.     gtk_widget_set_usize (abox, xsize, ysize * 4);
  905.   }
  906.   gtk_box_pack_start (GTK_BOX (toggle_vbox), abox, FALSE, FALSE, 0);
  907.   gtk_widget_show (abox);
  908.  
  909.   cmap_preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  910.   gtk_preview_size (GTK_PREVIEW (cmap_preview), 32, 32);
  911.   gtk_container_add (GTK_CONTAINER (abox), cmap_preview);
  912.   gtk_widget_show (cmap_preview);
  913.  
  914.   frame = add_objects_list ();
  915.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, 
  916.                 gtk_label_new (_("Fractals")));
  917.   gtk_widget_show (frame);
  918.  
  919.   gtk_notebook_set_page (GTK_NOTEBOOK (notebook), 1);
  920.  
  921.   /* Done */
  922.  
  923.   /* Popup for list area: Not yet fully implemented
  924.      fractalexplorer_op_menu_create(maindlg);
  925.   */
  926.  
  927.   gtk_widget_show (dialog);
  928.   ready_now = TRUE;
  929.  
  930.   set_cmap_preview ();
  931.   dialog_update_preview ();
  932.  
  933.   gtk_main ();
  934.   gimp_help_free ();
  935.   gdk_flush ();
  936.  
  937.   if (the_tile != NULL)
  938.     {
  939.       gimp_tile_unref (the_tile, FALSE);
  940.       the_tile = NULL;
  941.     }
  942.  
  943.   g_free (wint.wimage);
  944.  
  945.   return wint.run;
  946. }
  947.  
  948. /**********************************************************************
  949.  FUNCTION: dialog_update_preview
  950.  *********************************************************************/
  951.  
  952. void
  953. dialog_update_preview (void)
  954. {
  955.   gdouble  left;
  956.   gdouble  right;
  957.   gdouble  bottom;
  958.   gdouble  top;
  959.   gdouble  dx;
  960.   gdouble  dy;
  961.   gdouble  cx;
  962.   gdouble  cy;
  963.   gint     px;
  964.   gint     py;
  965.   gint     xcoord;
  966.   gint     ycoord;
  967.   gint     iteration;
  968.   guchar  *p_ul;
  969.   guchar  *p;
  970.   gdouble  a;
  971.   gdouble  b;
  972.   gdouble  x;
  973.   gdouble  y;
  974.   gdouble  oldx;
  975.   gdouble  oldy;
  976.   gdouble  foldxinitx;
  977.   gdouble  foldxinity;
  978.   gdouble  tempsqrx;
  979.   gdouble  tempsqry;
  980.   gdouble  tmpx = 0;
  981.   gdouble  tmpy = 0;
  982.   gdouble  foldyinitx;
  983.   gdouble  foldyinity;
  984.   gdouble  adjust;
  985.   gdouble  xx = 0;
  986.   gint     zaehler;
  987.   gint     color;
  988.   gint     useloglog;
  989.     
  990.   if (NULL == wint.preview)
  991.     return;
  992.  
  993.   if ((ready_now) && (wvals.alwayspreview))
  994.     {
  995.       left = sel_x1;
  996.       right = sel_x2 - 1;
  997.       bottom = sel_y2 - 1;
  998.       top = sel_y1;
  999.       dx = (right - left) / (preview_width - 1);
  1000.       dy = (bottom - top) / (preview_height - 1);
  1001.  
  1002.       xmin = wvals.xmin;
  1003.       xmax = wvals.xmax;
  1004.       ymin = wvals.ymin;
  1005.       ymax = wvals.ymax;
  1006.       cx = wvals.cx;
  1007.       cy = wvals.cy;
  1008.       xbild = preview_width;
  1009.       ybild = preview_height;
  1010.       xdiff = (xmax - xmin) / xbild;
  1011.       ydiff = (ymax - ymin) / ybild;
  1012.  
  1013.       py = 0;
  1014.  
  1015.       p_ul = wint.wimage;
  1016.       iteration = (int) wvals.iter;
  1017.       useloglog = wvals.useloglog;
  1018.       for (ycoord = 0; ycoord < preview_height; ycoord++)
  1019.     {
  1020.       px = 0;
  1021.  
  1022.       for (xcoord = 0; xcoord < preview_width; xcoord++)
  1023.         {
  1024.           a = (double) xmin + (double) xcoord *xdiff;
  1025.           b = (double) ymin + (double) ycoord *ydiff;
  1026.  
  1027.           if (wvals.fractaltype != TYPE_MANDELBROT)
  1028.         {
  1029.           tmpx = x = a;
  1030.           tmpy = y = b;
  1031.         }
  1032.           else
  1033.         {
  1034.           x = 0;
  1035.           y = 0;
  1036.         }
  1037.           for (zaehler = 0;
  1038.            (zaehler < iteration) && ((x * x + y * y) < 4);
  1039.            zaehler++)
  1040.         {
  1041.           oldx = x;
  1042.           oldy = y;
  1043.  
  1044.           switch (wvals.fractaltype)
  1045.             {
  1046.             case TYPE_MANDELBROT:
  1047.               xx = x * x - y * y + a;
  1048.               y = 2.0 * x * y + b;
  1049.               break;
  1050.  
  1051.             case TYPE_JULIA:
  1052.               xx = x * x - y * y + cx;
  1053.               y = 2.0 * x * y + cy; 
  1054.               break;
  1055.  
  1056.             case TYPE_BARNSLEY_1:
  1057.               foldxinitx = oldx * cx;
  1058.               foldyinity = oldy * cy;
  1059.               foldxinity = oldx * cy;
  1060.               foldyinitx = oldy * cx;
  1061.               /* orbit calculation */
  1062.               if (oldx >= 0)
  1063.             {
  1064.                   xx = (foldxinitx - cx - foldyinity);
  1065.                           y  = (foldyinitx - cy + foldxinity);
  1066.             }
  1067.               else
  1068.             {
  1069.                   xx = (foldxinitx + cx - foldyinity);
  1070.                   y  = (foldyinitx + cy + foldxinity);
  1071.             }
  1072.               break;
  1073.  
  1074.             case TYPE_BARNSLEY_2:
  1075.               foldxinitx = oldx * cx;
  1076.               foldyinity = oldy * cy;
  1077.               foldxinity = oldx * cy;
  1078.               foldyinitx = oldy * cx;
  1079.               /* orbit calculation */
  1080.               if (foldxinity + foldyinitx >= 0)
  1081.                         {
  1082.               xx = foldxinitx - cx - foldyinity;
  1083.               y  = foldyinitx - cy + foldxinity;
  1084.                         }
  1085.               else
  1086.                 {
  1087.               xx = foldxinitx + cx - foldyinity;
  1088.               y  = foldyinitx + cy + foldxinity;
  1089.                         }
  1090.               break;
  1091.  
  1092.             case TYPE_BARNSLEY_3:
  1093.               foldxinitx  = oldx * oldx;
  1094.               foldyinity  = oldy * oldy;
  1095.               foldxinity  = oldx * oldy;
  1096.               /* orbit calculation */
  1097.               if(oldx > 0)
  1098.             {
  1099.               xx = foldxinitx - foldyinity - 1.0;
  1100.               y  = foldxinity * 2;
  1101.             }
  1102.               else
  1103.             {
  1104.               xx = foldxinitx - foldyinity -1.0 + cx * oldx;
  1105.               y  = foldxinity * 2;
  1106.               y += cy * oldx;
  1107.             }
  1108.               break;
  1109.  
  1110.             case TYPE_SPIDER:
  1111.               /* { c=z=pixel: z=z*z+c; c=c/2+z, |z|<=4 } */
  1112.               xx = x*x - y*y + tmpx + cx;
  1113.               y = 2 * oldx * oldy + tmpy +cy;
  1114.               tmpx = tmpx/2 + xx;
  1115.               tmpy = tmpy/2 + y;
  1116.               break;
  1117.  
  1118.             case TYPE_MAN_O_WAR:
  1119.               xx = x*x - y*y + tmpx + cx;
  1120.               y = 2.0 * x * y + tmpy + cy;
  1121.               tmpx = oldx;
  1122.               tmpy = oldy;
  1123.               break;
  1124.  
  1125.             case TYPE_LAMBDA:
  1126.               tempsqrx = x * x;
  1127.               tempsqry = y * y;
  1128.               tempsqrx = oldx - tempsqrx + tempsqry;
  1129.               tempsqry = -(oldy * oldx);
  1130.               tempsqry += tempsqry + oldy;
  1131.               xx = cx * tempsqrx - cy * tempsqry;
  1132.               y = cx * tempsqry + cy * tempsqrx;
  1133.               break;
  1134.  
  1135.             case TYPE_SIERPINSKI:
  1136.               xx = oldx + oldx;
  1137.               y = oldy + oldy;
  1138.               if (oldy > .5)
  1139.             y = y - 1;
  1140.               else if (oldx > .5)
  1141.             xx = xx - 1;
  1142.               break;
  1143.  
  1144.             default:
  1145.               break;
  1146.             }
  1147.  
  1148.           x = xx;
  1149.         }
  1150.  
  1151.           if (useloglog)
  1152.         {
  1153.           adjust = log (log (x * x + y * y) / 2) / log (2);
  1154.         }
  1155.           else
  1156.         {
  1157.           adjust = 0.0;
  1158.         }
  1159.           color = (int) (((zaehler - adjust) *
  1160.                   (wvals.ncolors - 1)) / iteration);
  1161.           p_ul[0] = colormap[color][0];
  1162.           p_ul[1] = colormap[color][1];
  1163.           p_ul[2] = colormap[color][2];
  1164.           p_ul += 3;
  1165.           px += 1;
  1166.         } /* for */
  1167.       py += 1;
  1168.     } /* for */
  1169.  
  1170.       p = wint.wimage;
  1171.  
  1172.       for (y = 0; y < preview_height; y++)
  1173.     {
  1174.       gtk_preview_draw_row (GTK_PREVIEW (wint.preview), p,
  1175.                 0, y, preview_width);
  1176.       p += preview_width * 3;
  1177.     }
  1178.  
  1179.       gtk_widget_draw (wint.preview, NULL);
  1180.       gdk_flush ();
  1181.     }
  1182. }
  1183.  
  1184. /**********************************************************************
  1185.  FUNCTION: set_cmap_preview()
  1186.  *********************************************************************/
  1187.  
  1188. void
  1189. set_cmap_preview (void)
  1190. {
  1191.   gint    i;
  1192.   gint    x;
  1193.   gint    y;
  1194.   gint    j;
  1195.   guchar *b;
  1196.   guchar  c[GR_WIDTH * 3];
  1197.   gint    xsize, ysize;
  1198.  
  1199.   if (NULL == cmap_preview)
  1200.     return;
  1201.  
  1202.   make_color_map ();
  1203.  
  1204.   for (ysize = 1; ysize * ysize * ysize < wvals.ncolors; ysize++) /**/;
  1205.   xsize = wvals.ncolors / ysize;
  1206.   while (xsize * ysize < wvals.ncolors) xsize++;
  1207.   b = g_new (guchar, xsize * 3);
  1208.  
  1209.   gtk_preview_size     (GTK_PREVIEW (cmap_preview), xsize, ysize * 4);
  1210.   gtk_widget_set_usize (GTK_WIDGET (cmap_preview),  xsize, ysize * 4);
  1211.     
  1212.   for (y = 0; y < ysize*4; y += 4)
  1213.     {
  1214.       for (x = 0; x < xsize; x++)
  1215.     {
  1216.       i = x + (y / 4) * xsize;
  1217.       if (i > wvals.ncolors)
  1218.         {
  1219.           for (j = 0; j < 3; j++) 
  1220.         b[x * 3 + j] = 0;
  1221.         }
  1222.       else
  1223.         {
  1224.           for (j = 0; j < 3; j++)
  1225.         b[x * 3 + j] = colormap[i][j];
  1226.         }
  1227.     }
  1228.  
  1229.       gtk_preview_draw_row (GTK_PREVIEW (cmap_preview), b, 0, y, xsize);
  1230.       gtk_preview_draw_row (GTK_PREVIEW (cmap_preview), b, 0, y + 1, xsize);
  1231.       gtk_preview_draw_row (GTK_PREVIEW (cmap_preview), b, 0, y + 2, xsize);
  1232.       gtk_preview_draw_row (GTK_PREVIEW (cmap_preview), b, 0, y + 3, xsize);
  1233.     }
  1234.  
  1235.   for (x = 0; x < GR_WIDTH; x++)
  1236.     {
  1237.       for (j = 0; j < 3; j++)
  1238.     c[x * 3 + j] = colormap[(int)((float)x/(float)GR_WIDTH*256.0)][j];
  1239.     }
  1240.  
  1241.   gtk_widget_draw (cmap_preview, NULL);
  1242.  
  1243.   g_free (b);
  1244. }
  1245.  
  1246. /**********************************************************************
  1247.  FUNCTION: make_color_map()
  1248.  *********************************************************************/
  1249.  
  1250. void
  1251. make_color_map (void)
  1252. {
  1253.   gint     i;
  1254.   gint     j;
  1255.   gint     r;
  1256.   gint     gr;
  1257.   gint     bl;
  1258.   gdouble  redstretch;
  1259.   gdouble  greenstretch;
  1260.   gdouble  bluestretch;
  1261.   gdouble  pi = atan (1) * 4;
  1262.  
  1263.   /*  get gradient samples if they don't exist -- fixes gradient color
  1264.    *  mode for noninteractive use (bug #103470).
  1265.    */
  1266.   if (gradient_samples == NULL)
  1267.     gradient_samples = gimp_gradients_sample_uniform (wvals.ncolors);
  1268.  
  1269.   redstretch   = wvals.redstretch * 127.5;
  1270.   greenstretch = wvals.greenstretch * 127.5;
  1271.   bluestretch  = wvals.bluestretch * 127.5;
  1272.  
  1273.   for (i = 0; i < wvals.ncolors; i++)
  1274.     if (wvals.colormode == 1)
  1275.       {
  1276.     for (j = 0; j < 3; j++)
  1277.       colormap[i][j] = (int) (gradient_samples[i * 4 + j] * 255.0);
  1278.       }
  1279.     else
  1280.       {
  1281.     double x = (i*2.0) / wvals.ncolors;
  1282.     r = gr = bl = 0;
  1283.  
  1284.     switch (wvals.redmode)
  1285.       {
  1286.       case SINUS:
  1287.         r = (int) redstretch *(1.0 + sin((x - 1) * pi));
  1288.         break;
  1289.       case COSINUS:
  1290.         r = (int) redstretch *(1.0 + cos((x - 1) * pi));
  1291.         break;
  1292.       case NONE:
  1293.         r = (int)(redstretch *(x));
  1294.         break;
  1295.       default:
  1296.         break;
  1297.       }
  1298.  
  1299.     switch (wvals.greenmode)
  1300.       {
  1301.       case SINUS:
  1302.         gr = (int) greenstretch *(1.0 + sin((x - 1) * pi));
  1303.         break;
  1304.       case COSINUS:
  1305.         gr = (int) greenstretch *(1.0 + cos((x - 1) * pi));
  1306.         break;
  1307.       case NONE:
  1308.         gr = (int)(greenstretch *(x));
  1309.         break;
  1310.       default:
  1311.         break;
  1312.       }
  1313.  
  1314.     switch (wvals.bluemode)
  1315.       {
  1316.       case SINUS:
  1317.         bl = (int) bluestretch * (1.0 + sin ((x - 1) * pi));
  1318.         break;
  1319.       case COSINUS:
  1320.         bl = (int) bluestretch * (1.0 + cos ((x - 1) * pi));
  1321.         break;
  1322.       case NONE:
  1323.         bl = (int) (bluestretch * x);
  1324.         break;
  1325.       default:
  1326.         break;
  1327.       }
  1328.  
  1329.     r  = MIN (r,  255);
  1330.     gr = MIN (gr, 255);
  1331.     bl = MIN (bl, 255);
  1332.  
  1333.     if (wvals.redinvert)
  1334.       r = 255 - r;
  1335.  
  1336.     if (wvals.greeninvert)
  1337.       gr = 255 - gr;
  1338.  
  1339.     if (wvals.blueinvert)
  1340.       bl = 255 - bl;
  1341.  
  1342.     colormap[i][0] = r;
  1343.     colormap[i][1] = gr;
  1344.     colormap[i][2] = bl;
  1345.       }
  1346. }
  1347.  
  1348. /**********************************************************************
  1349.  FUNCTION: explorer_logo_dialog
  1350.  *********************************************************************/
  1351.  
  1352. static void
  1353. explorer_logo_dialog (void)
  1354. {
  1355.   GtkWidget *xdlg;
  1356.   GtkWidget *xlabel = NULL;
  1357.   GtkWidget *xlogo_box;
  1358.   GtkWidget *xpreview;
  1359.   GtkWidget *xframe;
  1360.   GtkWidget *xframe2;
  1361.   GtkWidget *xframe3;
  1362.   GtkWidget *xvbox;
  1363.   GtkWidget *xhbox;
  1364.   GtkWidget *vpaned;
  1365.   guchar *temp;
  1366.   guchar *temp2;
  1367.   guchar *datapointer;
  1368.   gint    y;
  1369.   gint    x;
  1370.  
  1371.   if (logodlg)
  1372.     {
  1373.       gdk_window_raise (logodlg->window);
  1374.       return;
  1375.     }
  1376.  
  1377.   xdlg = logodlg =
  1378.     gimp_dialog_new (_("About"), "fractalexplorer",
  1379.              gimp_standard_help_func, "filters/fractalexplorer.html",
  1380.              GTK_WIN_POS_MOUSE,
  1381.              FALSE, TRUE, FALSE,
  1382.  
  1383.              _("OK"), gtk_widget_destroy,
  1384.              NULL, 1, NULL, TRUE, TRUE,
  1385.  
  1386.              NULL);
  1387.  
  1388.   gtk_signal_connect (GTK_OBJECT (xdlg), "destroy",
  1389.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  1390.               &logodlg);
  1391.  
  1392.   xframe = gtk_frame_new (NULL);
  1393.   gtk_frame_set_shadow_type (GTK_FRAME (xframe), GTK_SHADOW_ETCHED_IN);
  1394.   gtk_container_set_border_width (GTK_CONTAINER (xframe), 6);
  1395.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (xdlg)->vbox), xframe, TRUE, TRUE, 0);
  1396.  
  1397.   xvbox = gtk_vbox_new (FALSE, 4);
  1398.   gtk_container_set_border_width (GTK_CONTAINER (xvbox), 4);
  1399.   gtk_container_add (GTK_CONTAINER (xframe), xvbox);
  1400.  
  1401.   /*  The logo frame & drawing area  */
  1402.   xhbox = gtk_hbox_new (FALSE, 5);
  1403.   gtk_box_pack_start (GTK_BOX (xvbox), xhbox, FALSE, TRUE, 0);
  1404.  
  1405.   xlogo_box = gtk_vbox_new (FALSE, 0);
  1406.   gtk_box_pack_start (GTK_BOX (xhbox), xlogo_box, FALSE, FALSE, 0);
  1407.  
  1408.   xframe2 = gtk_frame_new (NULL);
  1409.   gtk_frame_set_shadow_type(GTK_FRAME(xframe2), GTK_SHADOW_IN);
  1410.   gtk_box_pack_start(GTK_BOX(xlogo_box), xframe2, FALSE, FALSE, 0);
  1411.  
  1412.   xpreview = gtk_preview_new (GTK_PREVIEW_COLOR);
  1413.   gtk_preview_size (GTK_PREVIEW (xpreview), logo_width, logo_height);
  1414.   temp = g_malloc ((logo_width + 10) * 3);
  1415.   datapointer = header_data + logo_width * logo_height - 1;
  1416.  
  1417.   for (y = 0; y < logo_height; y++)
  1418.     {
  1419.       temp2 = temp;
  1420.       for (x = 0; x < logo_width; x++)
  1421.     {
  1422.       HEADER_PIXEL(datapointer, temp2);
  1423.       temp2 += 3;
  1424.     }
  1425.       gtk_preview_draw_row(GTK_PREVIEW(xpreview),
  1426.                temp,
  1427.                0, y, logo_width);
  1428.     }
  1429.  
  1430.   g_free (temp);
  1431.   gtk_container_add (GTK_CONTAINER (xframe2), xpreview);
  1432.   gtk_widget_show (xpreview);
  1433.   gtk_widget_show (xframe2);
  1434.   gtk_widget_show (xlogo_box);
  1435.   gtk_widget_show (xhbox);
  1436.  
  1437.   xhbox = gtk_hbox_new (FALSE, 5);
  1438.   gtk_box_pack_start (GTK_BOX (xvbox), xhbox, TRUE, TRUE, 0);
  1439.  
  1440.   vpaned = gtk_vpaned_new ();
  1441.   gtk_box_pack_start (GTK_BOX (xhbox), vpaned, TRUE, TRUE, 0);
  1442.   gtk_widget_show (vpaned);
  1443.     
  1444.   xframe3 = gtk_frame_new (NULL);
  1445.   gtk_paned_add1 (GTK_PANED (vpaned), xframe3);
  1446.   gtk_widget_show (xframe3);
  1447.  
  1448.   xlabel = gtk_label_new ("\nCotting Software Productions\n"
  1449.               "Quellenstrasse 10\n"
  1450.               "CH-8005 Zuerich (Switzerland)\n\n"
  1451.               "cotting@multimania.com\n"
  1452.               "http://www.multimania.com/cotting\n\n"
  1453.               "Fractal Chaos Explorer\nPlug-In for the GIMP\n"
  1454.               "Version 2.00 Beta 2 (Multilingual)\n");
  1455.   gtk_container_add (GTK_CONTAINER (xframe3),  xlabel);
  1456.   gtk_widget_show (xlabel);
  1457.  
  1458.   xframe3 = gtk_frame_new (NULL);
  1459.   gtk_paned_add2 (GTK_PANED (vpaned), xframe3);
  1460.   gtk_widget_show (xframe3);
  1461.  
  1462.   xlabel = gtk_label_new ("\nContains code from:\n\n"
  1463.               "Daniel Cotting\n<cotting@mygale.org>\n"
  1464.               "Peter Kirchgessner\n<Pkirchg@aol.com>\n"
  1465.               "Scott Draves\n<spot@cs.cmu.edu>\n"
  1466.               "Andy Thomas\n<alt@picnic.demon.co.uk>\n"
  1467.               "and the GIMP distribution.\n");
  1468.   gtk_container_add (GTK_CONTAINER (xframe3),  xlabel);
  1469.   gtk_widget_show (xlabel);
  1470.  
  1471.   gtk_widget_show (xhbox);
  1472.  
  1473.   gtk_widget_show (xvbox);
  1474.   gtk_widget_show (xframe);
  1475.   gtk_widget_show (xdlg);
  1476. }
  1477.  
  1478. /**********************************************************************
  1479.  FUNCTION: dialog_change_scale
  1480.  *********************************************************************/
  1481.  
  1482. void
  1483. dialog_change_scale (void)
  1484. {
  1485.   ready_now = FALSE;
  1486.  
  1487.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->xmin), wvals.xmin);
  1488.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->xmax), wvals.xmax);
  1489.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->ymin), wvals.ymin);
  1490.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->ymax), wvals.ymax);
  1491.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->iter), wvals.iter);
  1492.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->cx),   wvals.cx);
  1493.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->cy),   wvals.cy);
  1494.  
  1495.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->red),  wvals.redstretch);
  1496.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->green),wvals.greenstretch);
  1497.   gtk_adjustment_set_value (GTK_ADJUSTMENT (elements->blue), wvals.bluestretch);
  1498.  
  1499.   gtk_toggle_button_set_active
  1500.     (GTK_TOGGLE_BUTTON (elements->type[wvals.fractaltype]), TRUE);
  1501.  
  1502.   gtk_toggle_button_set_active
  1503.     (GTK_TOGGLE_BUTTON (elements->redmode[wvals.redmode]), TRUE);
  1504.   gtk_toggle_button_set_active
  1505.     (GTK_TOGGLE_BUTTON (elements->greenmode[wvals.greenmode]), TRUE);
  1506.   gtk_toggle_button_set_active
  1507.     (GTK_TOGGLE_BUTTON (elements->bluemode[wvals.bluemode]), TRUE);
  1508.  
  1509.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (elements->redinvert),
  1510.                 wvals.redinvert);
  1511.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (elements->greeninvert),
  1512.                 wvals.greeninvert);
  1513.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (elements->blueinvert),
  1514.                 wvals.blueinvert);
  1515.  
  1516.   gtk_toggle_button_set_active
  1517.     (GTK_TOGGLE_BUTTON (elements->colormode[wvals.colormode]), TRUE);
  1518.  
  1519.   ready_now = TRUE;
  1520. }
  1521.  
  1522.  
  1523. /**********************************************************************
  1524.  FUNCTION: save_options
  1525.  *********************************************************************/
  1526.  
  1527. void
  1528. save_options (FILE * fp)
  1529. {
  1530.   /* Save options */
  1531.   
  1532.   fprintf (fp, "fractaltype: %i\n", wvals.fractaltype);
  1533.   fprintf (fp, "xmin: %0.15f\n", wvals.xmin);
  1534.   fprintf (fp, "xmax: %0.15f\n", wvals.xmax);
  1535.   fprintf (fp, "ymin: %0.15f\n", wvals.ymin);
  1536.   fprintf (fp, "ymax: %0.15f\n", wvals.ymax);
  1537.   fprintf (fp, "iter: %0.15f\n", wvals.iter);
  1538.   fprintf (fp, "cx: %0.15f\n", wvals.cx);
  1539.   fprintf (fp, "cy: %0.15f\n", wvals.cy);
  1540.   fprintf (fp, "redstretch: %0.15f\n", wvals.redstretch * 128.0);
  1541.   fprintf (fp, "greenstretch: %0.15f\n", wvals.greenstretch * 128.0);
  1542.   fprintf (fp, "bluestretch: %0.15f\n", wvals.bluestretch * 128.0);
  1543.   fprintf (fp, "redmode: %i\n", wvals.redmode);
  1544.   fprintf (fp, "greenmode: %i\n", wvals.greenmode);
  1545.   fprintf (fp, "bluemode: %i\n", wvals.bluemode);
  1546.   fprintf (fp, "redinvert: %i\n", wvals.redinvert);
  1547.   fprintf (fp, "greeninvert: %i\n", wvals.greeninvert);
  1548.   fprintf (fp, "blueinvert: %i\n", wvals.blueinvert);
  1549.   fprintf (fp, "colormode: %i\n", wvals.colormode);
  1550.   fputs ("#**********************************************************************\n", fp);
  1551.   fprintf(fp, "<EOF>\n");
  1552.   fputs ("#**********************************************************************\n", fp);
  1553. }
  1554.  
  1555. /**********************************************************************
  1556.  FUNCTION: save_callback
  1557.  *********************************************************************/
  1558.  
  1559. void
  1560. save_callback (void)
  1561. {
  1562.   FILE  *fp;
  1563.   gchar *savename;
  1564.   gchar *message;
  1565.  
  1566.   savename = filename;
  1567.  
  1568.   fp = fopen (savename, "wt+");
  1569.  
  1570.   if (!fp) 
  1571.     {
  1572.       message = g_strconcat (_("Error opening: %s"), 
  1573.                  "\n",
  1574.                  _("Could not save."), 
  1575.                  savename);
  1576.       g_message (message);
  1577.       g_free (message);
  1578.       return;
  1579.     }
  1580.   /* Write header out */
  1581.   fputs (FRACTAL_HEADER, fp);
  1582.   fputs ("#**********************************************************************\n", fp);
  1583.   fputs ("# This is a data file for the Fractal Explorer plug-in for the GIMP   *\n", fp);
  1584.   fputs ("# Get the plug-in at              http://www.multimania.com/cotting   *\n", fp);
  1585.   fputs ("#**********************************************************************\n", fp);
  1586.  
  1587.   save_options (fp);
  1588.  
  1589.   if (ferror (fp))
  1590.     g_message (_("Failed to write file\n"));
  1591.   fclose (fp);
  1592. }
  1593.  
  1594. /**********************************************************************
  1595.  FUNCTION: file_selection_ok
  1596.  *********************************************************************/
  1597.  
  1598. void
  1599. file_selection_ok (GtkWidget        *w,
  1600.            GtkFileSelection *fs,
  1601.            gpointer          data)
  1602. {
  1603.   gchar       *filenamebuf;
  1604.   struct stat  filestat;
  1605.   gint         err;
  1606.  
  1607.   filenamebuf = gtk_file_selection_get_filename (GTK_FILE_SELECTION(fs));
  1608.  
  1609.   /* Get the name */
  1610.   if (strlen (filenamebuf) == 0)
  1611.     {
  1612.       g_message (_("Save: No filename given"));
  1613.       return;
  1614.     }
  1615.  
  1616.   /* Check if directory exists */
  1617.   err = stat (filenamebuf, &filestat);
  1618.  
  1619.   if (!err && S_ISDIR (filestat.st_mode))
  1620.     {
  1621.       /* Can't save to directory */
  1622.       g_message (_("Save: Can't save to a directory"));
  1623.       return;
  1624.     }
  1625.  
  1626.   filename = g_strdup (filenamebuf);
  1627.   save_callback ();
  1628.   gtk_widget_destroy (GTK_WIDGET (fs));
  1629. }
  1630.  
  1631. /**********************************************************************
  1632.  FUNCTION: load_file_selection_ok
  1633. **********************************************************************/
  1634.  
  1635. void
  1636. load_file_selection_ok (GtkWidget        *w,
  1637.             GtkFileSelection *fs,
  1638.             gpointer          data)
  1639. {
  1640.   struct stat filestat;
  1641.   gint        err;
  1642.  
  1643.   filename = g_strdup (gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
  1644.  
  1645.   err = stat (filename, &filestat);
  1646.  
  1647.   if (!err && S_ISREG (filestat.st_mode))
  1648.     {
  1649.       explorer_load ();
  1650.     }
  1651.  
  1652.   gtk_widget_destroy (GTK_WIDGET (fs));
  1653.   gtk_widget_show (maindlg);
  1654.   dialog_change_scale ();
  1655.   set_cmap_preview ();
  1656.   dialog_update_preview ();
  1657. }
  1658.  
  1659. /**********************************************************************
  1660.  FUNCTION: create_load_file_selection
  1661.  *********************************************************************/
  1662.  
  1663. void
  1664. create_load_file_selection (void)
  1665. {
  1666.   static GtkWidget *window = NULL;
  1667.  
  1668.   /* Load a single object */
  1669.   if (!window)
  1670.     {
  1671.       window = gtk_file_selection_new (_("Load Fractal Parameters"));
  1672.       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_NONE);
  1673.  
  1674.       gtk_signal_connect (GTK_OBJECT (window), "destroy",
  1675.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  1676.               &window);
  1677.  
  1678.       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (window)->ok_button),
  1679.               "clicked",
  1680.               GTK_SIGNAL_FUNC (load_file_selection_ok),
  1681.               (gpointer) window);
  1682.       gimp_help_set_help_data (GTK_FILE_SELECTION(window)->ok_button, _("Click here to load your file"), NULL);
  1683.  
  1684.       gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (window)->cancel_button),
  1685.                  "clicked",
  1686.                  GTK_SIGNAL_FUNC (gtk_widget_destroy),
  1687.                  GTK_OBJECT (window));
  1688.       gimp_help_set_help_data (GTK_FILE_SELECTION(window)->cancel_button, _("Click here to cancel load procedure"), NULL);
  1689.     }
  1690.  
  1691.   if (!GTK_WIDGET_VISIBLE (window))
  1692.     gtk_widget_show (window);
  1693. }
  1694.  
  1695. /**********************************************************************
  1696.  FUNCTION: create_file_selection
  1697.  *********************************************************************/
  1698.  
  1699. void
  1700. create_file_selection (void)
  1701. {
  1702.   static GtkWidget *window = NULL;
  1703.  
  1704.   if (!window)
  1705.     {
  1706.       window = gtk_file_selection_new (_("Save Fractal Parameters"));
  1707.       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_NONE);
  1708.  
  1709.       gtk_signal_connect (GTK_OBJECT (window), "destroy",
  1710.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  1711.               &window);
  1712.  
  1713.       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (window)->ok_button),
  1714.               "clicked",
  1715.               GTK_SIGNAL_FUNC (file_selection_ok),
  1716.               (gpointer) window);
  1717.       gimp_help_set_help_data (GTK_FILE_SELECTION(window)->ok_button,
  1718.                    _("Click here to save your file"), NULL);
  1719.  
  1720.       gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(window)->cancel_button),
  1721.                  "clicked",
  1722.                  GTK_SIGNAL_FUNC (gtk_widget_destroy),
  1723.                  GTK_OBJECT (window));
  1724.       gimp_help_set_help_data (GTK_FILE_SELECTION (window)->cancel_button,
  1725.                    _("Click here to cancel save procedure"), NULL);
  1726.     }
  1727.   if (tpath)
  1728.     {
  1729.       gtk_file_selection_set_filename (GTK_FILE_SELECTION (window), tpath);
  1730.     }
  1731.   else if (fractalexplorer_path_list)
  1732.     {
  1733.       gchar *dir;
  1734.  
  1735.       dir = gimp_path_get_user_writable_dir (fractalexplorer_path_list);
  1736.  
  1737.       if (!dir)
  1738.     dir = g_strdup (gimp_directory ());
  1739.  
  1740.       gtk_file_selection_set_filename (GTK_FILE_SELECTION (window), dir);
  1741.  
  1742.       g_free (dir);
  1743.     }
  1744.   else
  1745.     gtk_file_selection_set_filename (GTK_FILE_SELECTION (window),"/tmp");
  1746.  
  1747.   if (!GTK_WIDGET_VISIBLE (window))
  1748.     gtk_widget_show (window);
  1749. }
  1750.  
  1751. /**********************************************************************
  1752.  FUNCTION: get_line
  1753.  *********************************************************************/
  1754.  
  1755. gchar *
  1756. get_line (gchar *buf,
  1757.       gint   s,
  1758.       FILE  *from,
  1759.       gint   init)
  1760. {
  1761.   gint   slen;
  1762.   gchar *ret;
  1763.  
  1764.   if (init)
  1765.     line_no = 1;
  1766.   else
  1767.     line_no++;
  1768.  
  1769.   do
  1770.     {
  1771.       ret = fgets (buf, s, from);
  1772.     }
  1773.   while (!ferror (from) && buf[0] == '#');
  1774.  
  1775.   slen = strlen (buf);
  1776.  
  1777.   /* The last newline is a pain */
  1778.   if (slen > 0)
  1779.     buf[slen - 1] = '\0';
  1780.  
  1781.   if (ferror (from))
  1782.     {
  1783.       g_warning ("Error reading file");
  1784.       return NULL;
  1785.     }
  1786.  
  1787.   return ret;
  1788. }
  1789.  
  1790. /**********************************************************************
  1791.  FUNCTION: load_options
  1792.  *********************************************************************/
  1793.  
  1794. gint
  1795. load_options (fractalexplorerOBJ *xxx,
  1796.           FILE               *fp)
  1797. {
  1798.   gchar load_buf[MAX_LOAD_LINE];
  1799.   gchar str_buf[MAX_LOAD_LINE];
  1800.   gchar opt_buf[MAX_LOAD_LINE];
  1801.  
  1802.   /*  default values  */
  1803.   xxx->opts.fractaltype   =   0;
  1804.   xxx->opts.xmin          =  -2.0;
  1805.   xxx->opts.xmax          =   2.0;
  1806.   xxx->opts.ymin          =  -1.5;
  1807.   xxx->opts.ymax          =   1.5;
  1808.   xxx->opts.iter          =  50.0;
  1809.   xxx->opts.cx            =  -0.75;
  1810.   xxx->opts.cy            =  -0.2;
  1811.   xxx->opts.colormode     =   0;
  1812.   xxx->opts.redstretch    =   1.0;
  1813.   xxx->opts.greenstretch  =   1.0;
  1814.   xxx->opts.bluestretch   =   1.0;
  1815.   xxx->opts.redmode       =   1;
  1816.   xxx->opts.greenmode     =   1;
  1817.   xxx->opts.bluemode      =   1;
  1818.   xxx->opts.redinvert     =   0;
  1819.   xxx->opts.greeninvert   =   0;
  1820.   xxx->opts.blueinvert    =   0;
  1821.   xxx->opts.alwayspreview =   1;
  1822.   xxx->opts.ncolors       = 256;  /*  not saved  */
  1823.  
  1824.   get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1825.  
  1826.   while (!feof (fp) && strcmp (load_buf, "<EOF>"))
  1827.     {
  1828.       /* Get option name */
  1829.       sscanf (load_buf, "%s %s", str_buf, opt_buf);
  1830.  
  1831.       if (!strcmp (str_buf, "fractaltype:"))
  1832.     {
  1833.       gint sp = 0;
  1834.  
  1835.       sp = atoi (opt_buf);
  1836.       if (sp < 0)
  1837.         return -1;
  1838.       xxx->opts.fractaltype = sp;
  1839.     }
  1840.       else if (!strcmp (str_buf, "xmin:"))
  1841.     {
  1842.       gdouble sp = 0;
  1843.  
  1844.       sp = atof (opt_buf);
  1845.       xxx->opts.xmin = sp;
  1846.     }
  1847.       else if (!strcmp (str_buf, "xmax:"))
  1848.     {
  1849.       gdouble sp = 0;
  1850.  
  1851.       sp = atof (opt_buf);
  1852.       xxx->opts.xmax = sp;
  1853.     }
  1854.       else if (!strcmp(str_buf, "ymin:"))
  1855.     {
  1856.       gdouble sp = 0;
  1857.  
  1858.       sp = atof (opt_buf);
  1859.       xxx->opts.ymin = sp;
  1860.     }
  1861.       else if (!strcmp (str_buf, "ymax:"))
  1862.     {
  1863.       gdouble sp = 0;
  1864.  
  1865.       sp = atof (opt_buf);
  1866.       xxx->opts.ymax = sp;
  1867.     }
  1868.       else if (!strcmp(str_buf, "redstretch:"))
  1869.     {
  1870.       gdouble sp = 0;
  1871.  
  1872.       sp = atof (opt_buf);
  1873.       xxx->opts.redstretch = sp / 128.0;
  1874.     }
  1875.       else if (!strcmp(str_buf, "greenstretch:"))
  1876.     {
  1877.       gdouble sp = 0;
  1878.  
  1879.       sp = atof (opt_buf);
  1880.       xxx->opts.greenstretch = sp / 128.0;
  1881.     }
  1882.       else if (!strcmp (str_buf, "bluestretch:"))
  1883.     {
  1884.       gdouble sp = 0;
  1885.  
  1886.       sp = atof (opt_buf);
  1887.       xxx->opts.bluestretch = sp / 128.0;
  1888.     }
  1889.       else if (!strcmp (str_buf, "iter:"))
  1890.     {
  1891.       gdouble sp = 0;
  1892.  
  1893.       sp = atof (opt_buf);
  1894.       xxx->opts.iter = sp;
  1895.     }
  1896.       else if (!strcmp(str_buf, "cx:"))
  1897.     {
  1898.       gdouble sp = 0;
  1899.  
  1900.       sp = atof (opt_buf);
  1901.       xxx->opts.cx = sp;
  1902.     }
  1903.       else if (!strcmp (str_buf, "cy:"))
  1904.     {
  1905.       gdouble sp = 0;
  1906.  
  1907.       sp = atof (opt_buf);
  1908.       xxx->opts.cy = sp;
  1909.     }
  1910.       else if (!strcmp(str_buf, "redmode:"))
  1911.     {
  1912.       gint sp = 0;
  1913.  
  1914.       sp = atoi (opt_buf);
  1915.       xxx->opts.redmode = sp;
  1916.     }
  1917.       else if (!strcmp(str_buf, "greenmode:"))
  1918.     {
  1919.       gint sp = 0;
  1920.  
  1921.       sp = atoi (opt_buf);
  1922.       xxx->opts.greenmode = sp;
  1923.     }
  1924.       else if (!strcmp(str_buf, "bluemode:"))
  1925.     {
  1926.       gint sp = 0;
  1927.  
  1928.       sp = atoi (opt_buf);
  1929.       xxx->opts.bluemode = sp;
  1930.     }
  1931.       else if (!strcmp (str_buf, "redinvert:"))
  1932.     {
  1933.       gint sp = 0;
  1934.  
  1935.       sp = atoi (opt_buf);
  1936.       xxx->opts.redinvert = sp;
  1937.     }
  1938.       else if (!strcmp (str_buf, "greeninvert:"))
  1939.     {
  1940.       gint sp = 0;
  1941.  
  1942.       sp = atoi (opt_buf);
  1943.       xxx->opts.greeninvert = sp;
  1944.     }
  1945.       else if (!strcmp(str_buf, "blueinvert:"))
  1946.     {
  1947.       gint sp = 0;
  1948.  
  1949.       sp = atoi (opt_buf);
  1950.       xxx->opts.blueinvert = sp;
  1951.     }
  1952.       else if (!strcmp (str_buf, "colormode:"))
  1953.     {
  1954.       gint sp = 0;
  1955.  
  1956.       sp = atoi (opt_buf);
  1957.       xxx->opts.colormode = sp;
  1958.     }
  1959.  
  1960.       get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1961.     }
  1962.  
  1963.   return 0;
  1964. }
  1965.  
  1966. /**********************************************************************
  1967.  FUNCTION: explorer_load
  1968.  *********************************************************************/
  1969.  
  1970. void
  1971. explorer_load (void)
  1972. {
  1973.   FILE  *fp;
  1974.   gchar  load_buf[MAX_LOAD_LINE];
  1975.  
  1976.   g_assert (filename != NULL); 
  1977.   fp = fopen (filename, "rt");
  1978.  
  1979.   if (!fp)
  1980.     {
  1981.       g_warning ("Error opening: %s", filename);
  1982.       return;
  1983.     }
  1984.   get_line (load_buf, MAX_LOAD_LINE, fp, 1);
  1985.  
  1986.   if (strncmp (FRACTAL_HEADER, load_buf, strlen (load_buf)))
  1987.     {
  1988.       g_message (_("File '%s' is not a FractalExplorer file"), filename);
  1989.       return;
  1990.     }
  1991.   if (load_options (current_obj,fp))
  1992.     {
  1993.       g_message (_("File '%s' is corrupt.\nLine %d Option section incorrect"), 
  1994.          filename, line_no);
  1995.       return;
  1996.     }
  1997.  
  1998.   wvals = current_obj->opts;
  1999.   fclose (fp);
  2000. }
  2001.